package iot.emulator;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import iot.jtt808.DataPack;
import iot.jtt808.DataPackParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.atomic.AtomicLong;

/**
 * Created by dave on 18-7-21 下午12:26.
 */
public class EmulatorChannelHandler extends ChannelInboundHandlerAdapter {
    private static final Logger L = LoggerFactory.getLogger(EmulatorChannelHandler.class);
    private static final AtomicLong received = new AtomicLong(0);
    private String sim;

    public EmulatorChannelHandler(String sim) {
        this.sim = sim;
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        // L.debug("设备建立Socket连接:" + channel.remoteAddress());
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        closeChannel(ctx);
        L.debug("设备Socket断连：" + ctx.channel().remoteAddress());
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg.getClass().isArray() && msg.getClass().getComponentType() == byte.class) {
            DataPack dp = DataPackParser.parse((byte[]) msg);
            long seq = received.incrementAndGet();
            if (seq % 20000 == 0) {
                L.info("已接收到消息(万包)：" + seq / 10000);
            }
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        closeChannel(ctx);
        L.debug("出现异常：" + ctx.channel().remoteAddress(), cause);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent && ((IdleStateEvent) evt).state() == IdleState.READER_IDLE) {
            closeChannel(ctx);
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }

    private void closeChannel(ChannelHandlerContext ctx) {
        ctx.close();
    }

}
